#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>

#define NBR_THREADS 100
#define NBR_ITER 1000000000
#define MY_RAND_MAX 2147483647

void *func_thread(void *);
int old_gnu_rand_r (unsigned int *);

long int count_pieces[NBR_THREADS];

int main(int argc, char* argv[])
{
    pthread_t threads[NBR_THREADS];

    int i;
    long int count;
    double result;

    for(i = 0; i < NBR_THREADS; i++)
    {
        if(pthread_create(&threads[i], NULL, func_thread, (void *)i) < 0)
        {
            fprintf(stderr, "%s: %d: %s\n", __FILE__, __LINE__, strerror(errno));
            exit(EXIT_FAILURE);
        }
    }

    for(i = 0; i < NBR_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }

    count = 0;
    for(i = 0; i < NBR_THREADS; i++)
    {
        count += count_pieces[i];
    }

    result = ((double)count / NBR_ITER) * 4;
    printf("%lf\n", result);

    return 0;
}

void *func_thread(void *msg)
{
    int i = (int)msg;
    long int long_i, size = NBR_ITER / NBR_THREADS;
    long int start = i * size, end = (i + 1) * size;
    unsigned int seed = time(NULL);
    double x , y, z;

    count_pieces[i] = 0;
    for (long_i = start; long_i < end; long_i++)
    {
        x = (double)old_gnu_rand_r(&seed) / MY_RAND_MAX;
        y = (double)old_gnu_rand_r(&seed) / MY_RAND_MAX;
        z = (x * x) + (y * y);
        if (z <= 1) count_pieces[i]++;
    }

    return NULL;
}

int old_gnu_rand_r (unsigned int *seed)
{
    unsigned int next = *seed;
    int result;

    next *= 1103515245;
    next += 12345;
    result = (unsigned int) (next / 65536) % 2048;

    next *= 1103515245;
    next += 12345;
    result <<= 10;
    result ^= (unsigned int) (next / 65536) % 1024;

    next *= 1103515245;
    next += 12345;
    result <<= 10;
    result ^= (unsigned int) (next / 65536) % 1024;

    *seed = next;

    return result;
}

